﻿#include "cdatabaseopermgr.h"
#include <QMap>
#include <QReadWriteLock>
#include <QSqlDatabase>
#include <QSqlError>
#include <QEventLoop>
#include <QMutex>
#include <QDebug>
#include "cdbbaseoper.h"
#include "publiclog.h"
#include "cdbtableinfomgr.h"
#include "publicdefine.h"

#define MODULE_TYPE_DATABASE 0
const QString READ_CONNECT_NAME = "DatabaseOperRead";              //读连接名称
const QString WRITE_CONNECT_NAME = "DatabaseOperwrite";            //写连接名称
const int TRY_LOCK_TIME = 10;                                  //尝试加锁时间，单位ms
//const int JUDGE_IS_OPEN_TIME = 3000;                           //周期判断连接状态时间，单位ms
const int JUDGE_IS_OPEN_TIME = 10000;                           //周期判断连接状态时间，单位ms
const int WRITE_SQL_LOOP_TIME = 10;                            //同表写数据库周期时间，单位ms
const int DEFAULT_READ_CONNECT_NUMBER = 6;                     //默认读连接数量
const int DEFAULT_WRITE_CONNECT_NUMBER = 4;                    //默认写连接数量
const int g_nRetryNum = 3;                                     //尝试取得线程锁次数，超出则退出

//中文显示乱码问题
#define DB_A2T QString

/***********************************************
* [className]   CDatabaseOperMgrPrivate
* [func]        数据库管理数据类
* [author]      jhb
* [date]        2023-12-06 09:31
* [Modification Log]
* Version               By              Notes
* v0.0.1                jhb             初次建立
************************************************/
class CDatabaseOperMgrPrivate
{
    CDatabaseOperMgr *q_ptr;
    Q_DECLARE_PUBLIC(CDatabaseOperMgr)
public:
    CDatabaseOperMgrPrivate();
    virtual ~CDatabaseOperMgrPrivate();
    //设置数据库读写连接数
    bool setConnectNumber(const quint8 &nReadNum, const quint8 &nWriteNum);
    //设置数据库连接信息
    bool setDbConfigInfo(const CDataBaseConfig &stDbCfg);
    //设置数据库连接信息及库表名集合
    bool setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<QString> vecTableName);
    bool setDbConfigInfo(const CDataBaseConfig &stDbCfg, QStringList listTableName);
    bool setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<CDbTableInfo> vecTableInfo);
    //开启数据库连接
    bool open();
    //断开数据库连接
    void close();
    //判断数据库连接是否打开
    bool isOpen();
    //开启事务
    bool transaction(const QString &strId, int nType);
    //提交事务
    bool commit(const QString &strId);
    //回滚事务
    bool rollback(const QString &strId);
    //获取数据库操作信息指针
    CDbTableDataInfo *getDbDataInfo(const int &nTable, const int nType);
    CDbTableDataInfo *getDbDataInfo(const QString &strTable, const int nType);
    //获取执行结果
    bool getResult(const int &nTable, const int &nLock);
    bool getResult(const QString &strTable, const int &nLock);
    //写日志
    void writeLog(const QString &sLogText, int nType = CLogBase::enLevelInfo);
    //获取模块名
    QString getModuleName(const int &nType);

    //重连处理
    bool reconnect(QMap<QMutex*, CDbBaseOper*> mapDb);
    bool reconnect(QVector<CDbBaseOper*> vecDb);
    //事务连接绑定
    bool connectTransaction(const QString &strId, QMap<QMutex*, CDbBaseOper*> mapDb);
    bool connectTransaction(const QString &strId, QVector<CDbBaseOper*> vecDb);
    //执行语句
    bool execRead(CDbTableInfoMgr *pMgr);
    bool execWrite(CDbTableInfoMgr *pMgr);
    //事务执行
    bool execTransactionRead(CDbTableInfoMgr *pMgr);
    bool execTransactionWrite(CDbTableInfoMgr *pMgr);
    //锁列表内添加写锁表
    void AppendTableName(const QString &sTableName);
    //锁列表内移除写锁表
    void RemoveTableName(const QString &sTableName);
    //获取数据
    bool getSqlData(CDbBaseOper *pDb, CDbTableInfoMgr *pMgr);
    //初始化Sql数据
    bool initSqlData(CDbBaseOper *pDb, CDbTableInfoMgr *pMgr);

public:
    bool                            m_bIsOpen;              //是否成功调到Open接口打开数据库
    bool                            m_bIsSetNumber;         //是否调用成功SetConnectNumber接口标识
    quint8                          m_nReadNumber;          //读数据库连接数量
    quint8                          m_nWriteNumber;         //写数据库连接数量
    QVector<CDbBaseOper*>           m_vecReadDbOper;        //读连接
    QVector<CDbBaseOper*>           m_vecWriteDbOper;       //写连接
    QList<QString>                  m_listTableName;        //正在写表名列表
    QReadWriteLock                  m_lockTableName;        //表名读写锁
    CDataBaseConfig                 m_stDbCfg;              //数据库连接信息
    CLogBase                        *m_pLog;                //日志组件指针
    QVector<CDbTableInfoMgr*>       m_vecDbDataInfo;        //数据库表信息（执行SQL数据与表关联）
    QMap<QString, CDbBaseOper*>     m_mapTransID;           //ID与Sql事务绑定连接
    QMap<CDbBaseOper*, QString>     m_mapTransSql;          //Sql事务与ID绑定连接
    DbOpenDoneCallback              m_pDbOpenDoneCb;        //数据库打开成功回调
};

CDatabaseOperMgrPrivate::CDatabaseOperMgrPrivate()
{
    m_bIsOpen = false;
    m_bIsSetNumber = false;
    m_nReadNumber = DEFAULT_READ_CONNECT_NUMBER;
    m_nWriteNumber = DEFAULT_WRITE_CONNECT_NUMBER;
    m_vecReadDbOper.clear();
    m_vecWriteDbOper.clear();
    m_listTableName.clear();
    m_pLog = nullptr;
    m_vecDbDataInfo.clear();
    m_mapTransID.clear();
    m_mapTransSql.clear();
    m_pDbOpenDoneCb = nullptr;
}

CDatabaseOperMgrPrivate::~CDatabaseOperMgrPrivate()
{
    close();
}

bool CDatabaseOperMgrPrivate::setConnectNumber(const quint8 &nReadNum, const quint8 &nWriteNum)
{
    if (m_bIsSetNumber)
    {
        return false;
    }

    if (0 == nReadNum)
    {
        return false;
    }

    if (0 == nWriteNum)
    {
        return false;
    }
    m_nReadNumber = nReadNum;
    m_nWriteNumber = nWriteNum;
    m_bIsSetNumber = true;
    return true;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg)
{
    //入参判断
    if(stDbCfg.sIP.isEmpty()
            || stDbCfg.nPort < 0 || stDbCfg.nPort > 65535
            || stDbCfg.sName.isEmpty()
            || stDbCfg.sDBType.isEmpty()
            || stDbCfg.sUserName.isEmpty()) return false;

    m_stDbCfg = stDbCfg;
    return true;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<QString> vecTableName)
{
    bool bRet = setDbConfigInfo(stDbCfg);
    if(false == bRet) return false;
    if (vecTableName.isEmpty()) return false;
    bRet = false;
    for (int i = 0; i < vecTableName.size(); i++)
    {
        if (vecTableName.at(i).isEmpty()) continue;
        CDbTableInfoMgr *pInfo = new CDbTableInfoMgr;
        pInfo->m_sTableName = vecTableName.at(i);
        m_vecDbDataInfo.push_back(pInfo);
        bRet = true;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QStringList listTableName)
{
    bool bRet = setDbConfigInfo(stDbCfg);
    if(false == bRet) return false;
    if (listTableName.isEmpty()) return false;
    bRet = false;
    for (int i = 0; i < listTableName.size(); i++)
    {
        if (listTableName.at(i).isEmpty()) continue;
        CDbTableInfoMgr *pInfo = new CDbTableInfoMgr;
        pInfo->m_sTableName = listTableName.at(i);
        m_vecDbDataInfo.push_back(pInfo);
        bRet = true;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<CDbTableInfo> vecTableInfo)
{
    bool bRet = setDbConfigInfo(stDbCfg);
    if(false == bRet) return false;
    if (vecTableInfo.isEmpty()) return false;
    bRet = false;
    for (int i = 0; i < vecTableInfo.size(); i++)
    {
        if (vecTableInfo.at(i).sTableName.isEmpty()) continue;
        CDbTableInfoMgr *pInfo = new CDbTableInfoMgr;
        pInfo->m_sMode = vecTableInfo.at(i).sMode;
        pInfo->m_sTableName = vecTableInfo.at(i).sTableName;
        m_vecDbDataInfo.push_back(pInfo);
        bRet = true;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::open()
{
    //以防多次调用打开数据库
    if (m_bIsOpen)
    {
        return true;
    }

    //创建读连接
    if(m_vecReadDbOper.isEmpty())
    {
        int nReadNumber = m_nReadNumber;
        for (int i = 0; i < nReadNumber; ++i)
        {
            m_stDbCfg.sConnectName = QString("%1%2").arg(READ_CONNECT_NAME).arg(i);
            CDbBaseOper *pDatabase = CDbBaseOper::createCDbSqlOper(m_stDbCfg);
            if(nullptr == pDatabase)
            {
                qDebug() << "error";
            }
            if (nullptr != pDatabase && pDatabase->open())
            {
                pDatabase->setLogPtr(m_pLog);
                m_vecReadDbOper.append(pDatabase);
                //writeLog(QString(DB_A2T("【创建数据库连接】%1读连接创建成功"))
                //         .arg(pDatabase->m_db.connectionName()));
                writeLog(QObject::tr("[Create Database Connection] %1 read connection Create Successed")
                         .arg(pDatabase->m_db.connectionName()));
            }
            else
            {
                if(nullptr != pDatabase)
                {
                    //writeLog(QString(DB_A2T("【创建数据库连接】%1读连接创建失败,%2"))
                    //         .arg(pDatabase->m_db.connectionName())
                    //         .arg(pDatabase->m_db.lastError().text()), CLogBase::enLevelAlarm);
                    writeLog(QObject::tr("[Create Database Connection] %1 Read Connection Create Failed, %2")
                             .arg(pDatabase->m_db.connectionName())
                             .arg(pDatabase->m_db.lastError().text()), CLogBase::enLevelAlarm);
                    delete pDatabase;
                }
                return false; //创建失败退出，等待下个循环
            }
        }
    }

    //创建写连接
    //if (0 == m_mapWriteDatabase.size())
    if(m_vecWriteDbOper.isEmpty())
    {
        int nWriteNumber = m_nWriteNumber;
        for (int i = 0; i < nWriteNumber; ++i)
        {
            m_stDbCfg.sConnectName = QString("%1%2").arg(WRITE_CONNECT_NAME).arg(i);
            CDbBaseOper *pDatabase = CDbBaseOper::createCDbSqlOper(m_stDbCfg);
            if (nullptr != pDatabase && pDatabase->open())
            {
                pDatabase->setLogPtr(m_pLog);
                m_vecWriteDbOper.append(pDatabase);
                //writeLog(QString(DB_A2T("【创建数据库连接】%1写连接创建成功"))
                //         .arg(pDatabase->m_db.connectionName()));
                writeLog(QObject::tr("[Create Database Connection] %1 Write Connection Create Successed")
                         .arg(pDatabase->m_db.connectionName()));
            }
            else
            {
                if(nullptr != pDatabase)
                {
                    //writeLog(QString(DB_A2T("【创建数据库连接】%1写连接创建失败,%2"))
                    //         .arg(pDatabase->m_db.connectionName())
                    //         .arg(pDatabase->m_db.lastError().text()), CLogBase::enLevelAlarm);
                    writeLog(QObject::tr("[Create Database Connection] %1 Write Connection Create Failed, %2")
                             .arg(pDatabase->m_db.connectionName())
                             .arg(pDatabase->m_db.lastError().text()), CLogBase::enLevelAlarm);
                    delete pDatabase;
                }
                break;
            }
        }
    }

    if(m_nReadNumber != m_vecReadDbOper.size() ||
            m_nWriteNumber != m_vecWriteDbOper.size())
    {
        //数据库连接失败 则释放数据库资源
        close();
        return false;
    }

    m_bIsOpen = true;
    return true;
}

void CDatabaseOperMgrPrivate::close()
{
    m_bIsOpen = false;
    //清空读连接
    QVector<CDbBaseOper*> vec = m_vecReadDbOper;
    m_vecReadDbOper.clear();
    for(int i=0; i<vec.size(); ++i)
    {
        CDbBaseOper *pDb = vec.at(i);
        if(nullptr != pDb)
        {
            QString sConnectName = pDb->m_db.connectionName();
            pDb->m_db.close();
            delete pDb;
            pDb = nullptr;
            QSqlDatabase::removeDatabase(sConnectName);
        }
    }
    //清空写连接
    vec = m_vecWriteDbOper;
    m_vecWriteDbOper.clear();
    for(int i=0; i<vec.size(); ++i)
    {
        CDbBaseOper *pDb = vec.at(i);
        if(nullptr != pDb)
        {
            QString sConnectName = pDb->m_db.connectionName();
            pDb->m_db.close();
            delete pDb;
            pDb = nullptr;
            QSqlDatabase::removeDatabase(sConnectName);
        }
    }
    //释放数据库表信息
    QVector<CDbTableInfoMgr*> vecInfo = m_vecDbDataInfo;
    m_vecDbDataInfo.clear();
    foreach (CDbTableInfoMgr *pInfo, vecInfo)
    {
        if(nullptr == pInfo) continue;
        delete pInfo;
        pInfo = nullptr;
    }
}

bool CDatabaseOperMgrPrivate::isOpen()
{
    bool bReturn = false;
    //判断读连接状态，断开自动重连
    bReturn = reconnect(m_vecReadDbOper);
    //判断写连接状态，断开自动重连
    bReturn = reconnect(m_vecWriteDbOper);
    return bReturn;
}

bool CDatabaseOperMgrPrivate::transaction(const QString &strId, int nType)
{
    if(m_mapTransID.contains(strId)) return true;
    bool bRet = false;
    switch (nType)
    {
    case CDatabaseOperMgr::enDBRead:
        bRet = connectTransaction(strId, m_vecReadDbOper);
        break;
    case CDatabaseOperMgr::enDBWrite:
        bRet = connectTransaction(strId, m_vecWriteDbOper);
        break;
    default:
        break;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::commit(const QString &strId)
{
    if(false == m_mapTransID.contains(strId)) return true;
    CDbBaseOper *pDb = m_mapTransID.value(strId);
    bool bRet = pDb->m_db.commit();
    //提交成功，移除事务连接
    if(bRet)
    {
        m_mapTransID.remove(strId);
        m_mapTransSql.remove(pDb);
    }
    else
    {
        //提交失败，回滚
        pDb->m_db.rollback();
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::rollback(const QString &strId)
{
    if(false == m_mapTransID.contains(strId)) return false;
    CDbBaseOper *pDb = m_mapTransID.value(strId);
    bool bRet = pDb->m_db.rollback();
    //回滚后，不管成功与否，移除事务连接
    m_mapTransID.remove(strId);
    m_mapTransSql.remove(pDb);
    return bRet;
}

CDbTableDataInfo *CDatabaseOperMgrPrivate::getDbDataInfo(const int &nTable, const int nType)
{
    if((nTable < 0) || (nTable >= m_vecDbDataInfo.size()))
    {
        return nullptr;
    }
    CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(nTable);
    int nNum = 0;
    while(1)
    {
        //对资源进行锁定
        if(pInfo->tryLock(TRY_LOCK_TIME)) break;
        nNum++;
        //尝试次数到达则退出，否则线程可能死锁
        if (nNum > g_nRetryNum)
        {
            pInfo = nullptr;
            break;
        }
        //资源阻塞式访问
        if(enBLOCK == nType) continue;
        //非阻塞式访问
        pInfo = nullptr;
        break;
    }
    //清空资源
    if(nullptr != pInfo) pInfo->resetInfo();
    return pInfo;
}

CDbTableDataInfo *CDatabaseOperMgrPrivate::getDbDataInfo(const QString &strTable, const int nType)
{
    for (int i=0; i<m_vecDbDataInfo.size(); ++i)
    {
        CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(i);
        if(pInfo->m_sTableName != strTable) continue;
        return getDbDataInfo(i, nType);
    }
    return nullptr;
}

bool CDatabaseOperMgrPrivate::getResult(const int &nTable, const int &nLock)
{
    if((nTable < 0) || (nTable >= m_vecDbDataInfo.size()))
    {
        //writeLog(QString(DB_A2T("【数据库执行】库表索引异常， 未找到库表")), CLogBase::enLevelAlarm);
        writeLog(QObject::tr("[Database Operate] Table index exception, Table not found"), CLogBase::enLevelAlarm);
        return false;
    }
    bool bRet = false;
    CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(nTable);
    //Sql类型判断
    switch (pInfo->m_nWorkType)
    {
    case enSQLSELECT:
        bRet = execRead(pInfo);
        break;
    case enSQLUPDATE:
    case enSQLINSERT:
    case enSQLDELETE:
    case enSQLCREATE:
    case enSQLINSERTBATCH:
    case enSQLCUSTOM:
        bRet = execWrite(pInfo);
        break;
    default:
        break;
    }
    //资源锁判断
    switch (nLock) {
    case enLockNORMAL:
        //默认模式，自动解锁
        pInfo->unlock();
        break;
    case enLockSELECT:
        //非查询语句执行完成，或者语句执行失败，直接释放资源锁（查询语句可能需要解析数据，需要解析数据后手动释放）
        if((enSQLSELECT != pInfo->m_nWorkType &&
            enSQLSELECT != pInfo->m_nSqlType) || false == bRet)
            pInfo->unlock();
        break;
    case enLockALWAYS:
    default:
        //手动释放资源锁
        break;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::getResult(const QString &strTable, const int &nLock)
{
    for (int i=0; i<m_vecDbDataInfo.size(); ++i)
    {
        CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(i);
        if(pInfo->m_sTableName != strTable) continue;
        return getResult(i, nLock);
    }
    //writeLog(QString(DB_A2T("【数据库执行】%1未找到库表，请确认库表名配置正确")).arg(strTable), CLogBase::enLevelAlarm);
    writeLog(QObject::tr("[Database Operate] Table '%1' not found, please confirm table name configuration is correct")
             .arg(strTable), CLogBase::enLevelAlarm);
    return false;
}

void CDatabaseOperMgrPrivate::writeLog(const QString &sLogText, int nType)
{
    if(nullptr == m_pLog)
    {
        qDebug() << sLogText;
        return;
    }
    m_pLog->writeLog(QObject::tr("Database Module"), sLogText, nType, def_FL, 0);
}

bool CDatabaseOperMgrPrivate::reconnect(QMap<QMutex *, CDbBaseOper *> mapDb)
{
    bool bReturn = false;
    auto iteratorWrite = mapDb.constBegin();
    while (iteratorWrite != mapDb.constEnd())
    {
        QMutex *pMutex = iteratorWrite.key();
        CDbBaseOper *pDatabase = iteratorWrite.value();
        if (pMutex->tryLock(TRY_LOCK_TIME))
        {
            bReturn = pDatabase->isOpen();
            if (!bReturn)
            {
                //writeLog(QString(DB_A2T("【数据库重连】%1 连接断开，准备重连"))
                //         .arg(pDatabase->m_db.connectionName()), CLogBase::enLevelAlarm);
                writeLog(QObject::tr("[Database Reconnection] %1 disconnet, prepare for reconnection")
                         .arg(pDatabase->m_db.connectionName()), CLogBase::enLevelAlarm);
                pDatabase->m_db.close();
                bReturn = pDatabase->m_db.open();
                if (!bReturn)
                {
                    //writeLog(QString(DB_A2T("【数据库重连】写重连失败原因：%1"))
                    //         .arg(pDatabase->m_db.lastError().text()), CLogBase::enLevelAlarm);
                    writeLog(QObject::tr("[Database Reconnection] Write reconnection failed, Reason : %1")
                             .arg(pDatabase->m_db.lastError().text()), CLogBase::enLevelAlarm);
                }
                else
                {
                    //writeLog(QString(DB_A2T("【数据库重连】%1 重连成功"))
                    //         .arg(pDatabase->m_db.connectionName()));
                    writeLog(QObject::tr("[Database Reconnection] %1 reconnection successed")
                             .arg(pDatabase->m_db.connectionName()));
                }
                pMutex->unlock();
            }
            else
            {
                pMutex->unlock();
                break;
            }
        }
        else
        {
            bReturn = true;
        }

        ++iteratorWrite;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::reconnect(QVector<CDbBaseOper *> vecDb)
{
    bool bReturn = false;
    for(int i=0; i<vecDb.size(); ++i)
    {
        CDbBaseOper *pDb = vecDb.at(i);
        if(pDb->tryLock(TRY_LOCK_TIME))
        {
            bReturn = pDb->isOpen();
            if (!bReturn)
            {
                //writeLog(QString(DB_A2T("【数据库重连】%1 连接断开，准备重连"))
                //         .arg(pDb->m_db.connectionName()), CLogBase::enLevelAlarm);
                writeLog(QObject::tr("[Database Reconnection] %1 disconnet, prepare for reconnection")
                         .arg(pDb->m_db.connectionName()), CLogBase::enLevelAlarm);
                pDb->m_db.close();
                bReturn = pDb->m_db.open();
                if (!bReturn)
                {
                    //writeLog(QString(DB_A2T("【数据库重连】%1重连失败原因：%2"))
                    //         .arg(pDb->m_db.connectionName())
                    //         .arg(pDb->m_db.lastError().text()), CLogBase::enLevelAlarm);
                    writeLog(QObject::tr("[Database Reconnection] %1 reconnection failed, Reason : %2")
                             .arg(pDb->m_db.connectionName())
                             .arg(pDb->m_db.lastError().text()), CLogBase::enLevelAlarm);
                }
                else
                {
                    //writeLog(QString(DB_A2T("【数据库重连】%1 重连成功"))
                    //         .arg(pDb->m_db.connectionName()));
                    writeLog(QObject::tr("[Database Reconnection] %1 reconnection successed")
                             .arg(pDb->m_db.connectionName()));
                }
                pDb->unlock();
            }
            else
            {
                pDb->unlock();
            }
        }
        else bReturn = true;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::connectTransaction(const QString &strId, QMap<QMutex *, CDbBaseOper *> mapDb)
{
    bool bRet = false;
    auto it = mapDb.constBegin();
    while ( it != mapDb.constEnd() )
    {
        QMutex *pMutex = it.key();
        CDbBaseOper *pDatabase = it.value();
        if (pMutex->tryLock(TRY_LOCK_TIME))
        {
            //此连接已开启事务，寻找下一个
            if(m_mapTransSql.contains(pDatabase))
            {
                pMutex->unlock();
                ++it;
                if (it == mapDb.constEnd())
                {
                    it = mapDb.constBegin();
                }
                continue;
            }
            bRet = pDatabase->m_db.transaction();
            //开启事务失败，寻找下一个
            if(false == bRet)
            {
                pMutex->unlock();
                ++it;
                if (it == mapDb.constEnd())
                {
                    it = mapDb.constBegin();
                }
                continue;
            }
            //事务开启成功
            m_mapTransID.insert(strId, pDatabase);
            m_mapTransSql.insert(pDatabase, strId);
            pMutex->unlock();
            break;
        }
        ++it;
        if (it == mapDb.constEnd())
        {
            it = mapDb.constBegin();
        }
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::connectTransaction(const QString &strId, QVector<CDbBaseOper *> vecDb)
{
    bool bRet = false;
    for(int i=0; i<vecDb.size(); )
    {
        CDbBaseOper *pDb = vecDb.at(i);
        if (pDb->tryLock(TRY_LOCK_TIME))
        {
            //此连接已开启事务，寻找下一个
            if(m_mapTransSql.contains(pDb))
            {
                pDb->unlock();
                ++i;
                if (i == vecDb.size()) i=0;
                continue;
            }
            bRet = pDb->m_db.transaction();
            //开启事务失败，寻找下一个
            if(false == bRet)
            {
                pDb->unlock();
                ++i;
                if (i == vecDb.size()) i=0;
                continue;
            }
            //事务开启成功
            m_mapTransID.insert(strId, pDb);
            m_mapTransSql.insert(pDb, strId);
            pDb->unlock();
            break;
        }
        ++i;
        if (i == vecDb.size()) i=0;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::execRead(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(false == pMgr->m_sTransactionID.isEmpty())
    {
        return execTransactionRead(pMgr);
    }

    bool bReturn = false;
    for(int i=0; i<m_vecReadDbOper.size(); )
    {
        CDbBaseOper *pDb = m_vecReadDbOper.at(i);
        if (false == pDb->tryLock(TRY_LOCK_TIME))
        {
            ++i;
            if(i == m_vecReadDbOper.size()) i=0;
            continue;
        }
        bReturn = getSqlData(pDb, pMgr);
        pDb->unlock();
        break;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::execWrite(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(false == pMgr->m_sTransactionID.isEmpty())
    {
        return execTransactionWrite(pMgr);
    }

    bool bReturn = false;
    for(int i=0; i<m_vecWriteDbOper.size(); )
    {
        CDbBaseOper *pDb = m_vecWriteDbOper.at(i);
        if (false == pDb->tryLock(TRY_LOCK_TIME))
        {
            ++i;
            if(i == m_vecWriteDbOper.size()) i=0;
            continue;
        }
        bReturn = getSqlData(pDb, pMgr);
        pDb->unlock();
        break;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::execTransactionRead(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(pMgr->m_sTransactionID.isEmpty())
    {
        return execRead(pMgr);
    }

    bool bReturn = false;

    //未找到事务执行连接，返回失败
    if(false == m_mapTransID.contains(pMgr->m_sTransactionID)) return false;
    CDbBaseOper *pDb = m_mapTransID.value(pMgr->m_sTransactionID);
    while(1)
    {
        //尝试加锁
        if (false == pDb->tryLock(TRY_LOCK_TIME))
        {
            //尝试加锁失败
            QEventLoop loop;
            QTimer::singleShot(WRITE_SQL_LOOP_TIME, &loop, SLOT(quit()));
            loop.exec();
            continue;
        }
        bReturn = getSqlData(pDb, pMgr);
        pDb->unlock();
        break;
    }

    return bReturn;
}

bool CDatabaseOperMgrPrivate::execTransactionWrite(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(pMgr->m_sTransactionID.isEmpty())
    {
        return execWrite(pMgr);
    }

    bool bReturn = false;
    while(true)
    {
        m_lockTableName.lockForRead();
        if (m_listTableName.contains(pMgr->m_sTableName))
        {
            m_lockTableName.unlock();
            QEventLoop loop;
            QTimer::singleShot(WRITE_SQL_LOOP_TIME, &loop, SLOT(quit()));
            loop.exec();
            continue;
        }
        m_lockTableName.unlock();
        //未找到事务执行连接，返回失败
        if(false == m_mapTransID.contains(pMgr->m_sTransactionID)) return false;
        CDbBaseOper *pDb = m_mapTransID.value(pMgr->m_sTransactionID);
        while(1)
        {
            //尝试加锁
            if (false == pDb->tryLock(TRY_LOCK_TIME))
            {
                //尝试加锁失败
                QEventLoop loop;
                QTimer::singleShot(WRITE_SQL_LOOP_TIME, &loop, SLOT(quit()));
                loop.exec();
                continue;
            }
            //写数据库加锁
            AppendTableName(pMgr->m_sTableName);
            bReturn = getSqlData(pDb, pMgr);
            pMgr->m_sTransactionID = "";
            RemoveTableName(pMgr->m_sTableName);
            pDb->unlock();
            break;
        }
        break;
    }

    return bReturn;
}

void CDatabaseOperMgrPrivate::AppendTableName(const QString &sTableName)
{
    m_lockTableName.lockForWrite();
    m_listTableName.append(sTableName);
    m_lockTableName.unlock();
}

void CDatabaseOperMgrPrivate::RemoveTableName(const QString &sTableName)
{
    m_lockTableName.lockForWrite();
    if (!m_listTableName.isEmpty())
    {
        m_listTableName.removeOne(sTableName);
    }
    m_lockTableName.unlock();
}

bool CDatabaseOperMgrPrivate::getSqlData(CDbBaseOper *pDb, CDbTableInfoMgr *pMgr)
{
    //判断数据是否初始化
    if(false == pMgr->m_bInitRecord)
    {
        if(false == initSqlData(pDb, pMgr))
            return pMgr->m_bSqlOperIsOk;
    }
    pDb->handleSql(pMgr);
    return pMgr->m_bSqlOperIsOk;
}

bool CDatabaseOperMgrPrivate::initSqlData(CDbBaseOper *pDb, CDbTableInfoMgr *pMgr)
{
    pDb->initTableInfo(pMgr);
    if (pMgr->m_bSqlOperIsOk)
    {
        pMgr->m_bInitRecord = true;
        return true;
    }
    return false;
}

/***********************************************
* [className]   CDatabaseOperMgr
* [func]        数据库管理类
* [author]      jhb
* [date]        2023-12-06 09:13
* [Modification Log]
* Version               By              Notes
* v0.0.1                jhb             初次建立
************************************************/
CDatabaseOperMgr::CDatabaseOperMgr()
{
    d_ptr = new CDatabaseOperMgrPrivate;
    d_ptr->q_ptr = this;
}

CDatabaseOperMgr::~CDatabaseOperMgr()
{
    d_ptr->close();
    SAFE_DELETE(d_ptr)
}

//设置数据库读写连接数量
bool CDatabaseOperMgr::setConnectNumber(const quint8 &nReadNum, const quint8 &nWriteNum)
{
    return d_ptr->setConnectNumber(nReadNum, nWriteNum);
}

//设置数据库连接信息
bool CDatabaseOperMgr::setDbConfigInfo(const CDataBaseConfig &stDbCfg)
{
    return d_ptr->setDbConfigInfo(stDbCfg);
}

//设置数据库连接信息
bool CDatabaseOperMgr::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<QString> vecTableName)
{
    return d_ptr->setDbConfigInfo(stDbCfg, vecTableName);
}

//设置数据库连接信息
bool CDatabaseOperMgr::setDbConfigInfo(const CDataBaseConfig &stDbCfg, const QString &strTables)
{
    QStringList strList = strTables.split(",");
    return d_ptr->setDbConfigInfo(stDbCfg, strList);
}

//设置数据库连接信息
bool CDatabaseOperMgr::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<CDbTableInfo> vecTableInfo)
{
    return d_ptr->setDbConfigInfo(stDbCfg, vecTableInfo);
}

//开启事务
bool CDatabaseOperMgr::transaction(const QString &strId, int nType)
{
    if(false == d_ptr->m_bIsOpen) return false;
    return d_ptr->transaction(strId, nType);
}

//提交事务
bool CDatabaseOperMgr::commit(const QString &strId)
{
    if(false == d_ptr->m_bIsOpen) return false;
    return d_ptr->commit(strId);
}

//回滚事务
bool CDatabaseOperMgr::rollback(const QString &strId)
{
    if(false == d_ptr->m_bIsOpen) return false;
    return d_ptr->rollback(strId);
}

//获取数据库操作信息
CDbTableDataInfo *CDatabaseOperMgr::getDbDataInfo(const int &nTable, const int &nLock)
{
    if(false == d_ptr->m_bIsOpen) return nullptr;
    return d_ptr->getDbDataInfo(nTable, nLock);
}

//获取数据库操作信息
CDbTableDataInfo *CDatabaseOperMgr::getDbDataInfo(const QString &strTable, const int &nLock)
{
    if(false == d_ptr->m_bIsOpen) return nullptr;
    return d_ptr->getDbDataInfo(strTable, nLock);
}

//获取执行结果
bool CDatabaseOperMgr::getResult(const int &nTable, const int &nLock)
{
    if(false == d_ptr->m_bIsOpen) return false;
    return d_ptr->getResult(nTable, nLock);
}

//获取执行结果
bool CDatabaseOperMgr::getResult(const QString &strTable, const int &nLock)
{
    if(false == d_ptr->m_bIsOpen) return false;
    return d_ptr->getResult(strTable, nLock);
}

//设置日志组件指针
void CDatabaseOperMgr::setLogPtr(CLogBase *pLog)
{
    d_ptr->m_pLog = pLog;
}

//设置数据库打开成功回调函数
bool CDatabaseOperMgr::setDbOpenDoneCb(DbOpenDoneCallback func)
{
    d_ptr->m_pDbOpenDoneCb = func;
    return true;
}

//使用结构体数据直接执行SQL
bool CDatabaseOperMgr::exec(CDatabaseExecData &data, const int &nLock)
{
    if(false == d_ptr->m_bIsOpen) return false;
    qDebug() << data.sTableName;
    CDbTableDataInfo *pInfo = getDbDataInfo(data.sTableName);
    if(nullptr == pInfo)
    {
        qDebug() << "1";
        data.sErr = QObject::tr("Table occupied, sql executing failed");
        return false;
    }
    //SQL操作类型
    pInfo->setWorkType(enSQLCUSTOM);
    //问号占位符处理
    if((false == data.vecField.isEmpty())
            && (false == data.vecValue.isEmpty()))
    {
        pInfo->addResultField(data.vecField);
        pInfo->addResultValue(data.vecValue);
    }
    //添加SQL
    qDebug() << data.sSql;
    pInfo->addSql(data.sSql);
    //执行SQL
    bool bRet = getResult(data.sTableName, enLockALWAYS);
    //执行失败，手动释放资源锁
    if(false == bRet)
    {
        data.sErr = pInfo->getLastError();
        if(enNONBLOCK == nLock) pInfo->unlock();
        return bRet;
    }
    //查询语句特殊处理
    if(enSQLSELECT == pInfo->getSqlType())
    {
        //获取数据
        data.vecRecord = pInfo->getReRecord();
    }
    //手动释放资源锁
    if(enNONBLOCK == nLock) pInfo->unlock();
    return bRet;
}

//工作线程
void CDatabaseOperMgr::slotWorkProc()
{
    bool bStartFlag = false;
    while (false == m_bStopWorkThread)
    {
        bStartFlag = true;
        if(false == d_ptr->m_bIsOpen)
        {
            bool bDBOpen = d_ptr->open();
            if(bDBOpen)
            {
                //通知数据库打开成功
                if (d_ptr->m_pDbOpenDoneCb) (d_ptr->m_pDbOpenDoneCb)();
                emit sigDbOpenDone();
            }

            if(false == d_ptr->m_bIsOpen)
            {
                threadSleep(5000);
                continue;
            }
        }
        else
        {
            //判断数据库连接状态,并在内部自动重连
            d_ptr->isOpen();
        }
        threadSleep(JUDGE_IS_OPEN_TIME);
    }
    //启动后被停止，需要清理数据
    if(bStartFlag)
    {
        d_ptr->close();
    }
}
